<?php

namespace app\site\controller\store;

use app\common\exception\MiException;
use app\model\store\Goods;
use app\model\store\GoodsCateRel;
use app\model\store\GoodsSku;
use app\model\store\GoodsSkuSpecRel;
use app\model\store\GoodsSpec;
use app\model\store\GoodsSpecValue;
use app\model\store\GoodsTagRel;
use app\site\controller\AController;
use app\site\service\CurdService;
use app\site\service\SiteAuthService;
use app\site\service\SiteReqService;
use app\site\service\store\GoodsService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use think\Request;
use think\response\Json;

class GoodsController extends AController
{


    /**
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function index (): Json
    {

        $where = [];
        $key = $this->param('where.key');
        $showType = $this->param('where.show_type');
        $stockDanger = $this->param('where.stockDanger');

        if ($key) $where[] = ['title', 'like', '%'.$key.'%'];   // 关键词
        if ($showType) $where[] = ['show_type', '=', $showType];    // 上下架
        if ($stockDanger) $where[] = ['stock', 'exp', Db::raw(' <= `stock_danger` ')];   // 库存预警

        $goodsSer = GoodsService::instance()
            ->setWhereCateId($filter['cate_id']??0)
            ->setWhere($where);
        return $this->reqSer->setService($goodsSer)->setPaginate()->getResponse();
    }

    /**
     * 获取不分页的商品列表
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function list(){
        $goodsIds = $this->param('goods_ids', '');
        $cateId = $this->param('cate_id', 0);
        $tagId = $this->param('tag_id',0);
        $limit = $this->param('limit', 0);
        $where = [];
        if ($goodsIds) $where[] = ['id', 'in',$goodsIds];

        $ser = GoodsService::instance()
            ->setLimit($limit)
            ->setWhereCateId($cateId)
            ->setWhereTagId($tagId)
            ->setWhere($where);
        return SiteReqService::instance()->setService($ser)->setSelect()->getResponse();
    }


    /**
     * @throws \Exception
     */
    public function add(Request $request): Json
    {
        $post = $this->post();

        $this->save($post, 'add');

        return jsonSuccess();
    }

    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws \Exception
     */
    public function edit(Request $request): Json
    {
        if ($request->isPost()){
            $post = $this->post();
            $this->save($post, 'edit');
            return jsonSuccess();
        }else{
            $goodsSer =GoodsService::instance();
            return SiteReqService::instance()->setService($goodsSer)->setFind()->getResponse();
        }

    }

    /**
     */
    public function del(): Json
    {

        $ids = $this->param('ids');

        Db::transaction(function () use ($ids) {
            if ($ids && count($ids)){

                Goods::where('id', 'in', $ids)->delete();

                foreach ($ids as $goods_id){
                    // 删除关联分类
                    GoodsCateRel::where('goods_id', $goods_id)->delete();
                    // 删除关联标签
                    GoodsTagRel::where('goods_id', $goods_id)->delete();
                    // 删除sku
                    GoodsSku::where('goods_id', $goods_id)->delete();
                    // 删除规格
                    GoodsSpec::where('goods_id', $goods_id)->delete();
                    // 删除规格值
                    GoodsSpecValue::where('goods_id', $goods_id)->delete();
                    // 删除规格和sku的关联
                    GoodsSkuSpecRel::where('goods_id', $goods_id)->delete();
                }
            }

        });

        return jsonSuccess();

    }

    /**
     * 上架/下架操作
     * @return Json
     */
    public function updateShowType(): Json
    {
        // 权限验证
        $isAuth = SiteAuthService::instance()->checkLoginAuth('goods/edit');
        if (!$isAuth) return jsonError("无权限");

        $ids = $this->post('ids');
        $show = $this->post('show_type', 0);
        if (!$ids) return jsonError(PARAM_ERROR);

        GoodsService::instance()->update(['show_type'=>$show], [
            ['id','in', $ids]
        ]);
        return jsonSuccess();


    }

    /**
     * @throws \Exception
     */
    private function save(array $post, string $type){
        if (!in_array($type, ['add', 'edit'])){
            throw new \Exception(PARAM_ERROR);
        }
        $post['images'] = miImplode($post['imageArr']);
        // 验证数据
        validate("")->check($post);
        Db::transaction(function () use ($type, $post) {
            $siteId = SiteAuthService::instance()->getSiteId();
            $curdGoods = new CurdService(new Goods());
            if ($type == 'edit'){
                $id = $post['id'];
                $goods = $curdGoods->update($post, ['id' => $id]);
            }else{
                $goods = $curdGoods->create($post);
            }
            // 关联分类
            // 删除旧的分类关联
            GoodsCateRel::where('goods_id', '=', $goods->id)->delete();
            $cateIds = $post['cate_ids']??[];
            foreach ($cateIds as $cateId){
                GoodsCateRel::create([
                    'id' => uuid(),
                    'site_id' => $siteId,
                    'goods_id' => $goods->id,
                    'cate_id' => $cateId,
                ]);
            }
            // 关联标签
            // 删除旧的标签关联
            GoodsTagRel::where('goods_id', '=', $goods->id)->delete();
            $tagIds = $post['tag_ids']??[];
            foreach ($tagIds as $tagId){
                GoodsTagRel::create([
                    'id' => uuid(),
                    'site_id' => $siteId,
                    'goods_id' => $goods->id,
                    'tag_id' => $tagId,
                ]);
            }

            if ($post['spec_type'] == 2){ // 多规格
                $skus = $post['skus'];
                $specs = $post['specs'];
                $this->editSku($goods, $specs, $skus);
            }
        });

    }


    /**
     * 编辑产品规格，每次编辑规格都会先删除所有原规格，再重新添加所有规格，并修改商品价格库存等信息
     * @param Goods $goods
     * @param array $specs
     * @param array $skus
     * @return void
     */
    private function editSku(Goods $goods, array $specs, array $skus){

        if ($goods->spec_type == 1){  // 单规格不进行操作
            return;
        }

        $gid = $goods->id;
        $siteId = $goods->site_id;
        $skuId = GoodsSku::where('goods_id', $gid)->column("id");
        // 删除原产品规格，不要使用软删除
        Db::table('goods_spec')->where('goods_id', $gid)->delete();
        Db::table('goods_spec_value')->where('goods_id', $gid)->delete();
        Db::table('goods_sku')->where('goods_id', $gid)->delete();
        Db::table('goods_sku_spec_rel')->where('sku_id', 'in', $skuId)->delete();
        $priceArr = [];    // 所有规格的售价数据
        $linePriceArr = [];  // 所有规格中的划线价数组
        $costPriceArr = [];  // 所有规格中的成本价
        $stockTotal = 0;      // 所有规格中的总库存
        $stockFlag = false;    // 是否不限库存（只要有一个规格不限库存，总库存即为不限）

        $afterSaveSpecs = [];
        // 编辑产品规格
        foreach ($specs as $v){
            $goodsSpec = GoodsSpec::create([
                'site_id' =>SiteAuthService::instance()->getSiteId(),
                'goods_id' => $gid,
                'title' => $v['title'],
            ]);

            $afterSaveVals = [];
            foreach ($v['values'] as $vv){
                $sVal = GoodsSpecValue::create([
                   'site_id' => SiteAuthService::instance()->getSiteId(),
                    'goods_id' => $gid,
                    'spec_id' => $goodsSpec->id,
                    'value' => $vv['value'],
                ]);
                $afterSaveVals[$vv['vir_id']] = $sVal;
            }
            $goodsSpec['values'] = $afterSaveVals;

            $afterSaveSpecs[$v['vir_id']] = $goodsSpec;
        }

        foreach ($skus as $sku) {
//            $sku['id'] = uuid();
            // 不限库存存入-1，并将总库存数量不限的标记stockFlag = true
            if (!$sku['stock'] && $sku['stock']!==0){
                $sku['stock'] = -1;
                $stockFlag = true;
            }
            // 保存
            $resSku = GoodsSku::create([
                'site_id' => SiteAuthService::instance()->getSiteId(),
                'goods_id' => $gid,
                'stock' => $sku['stock'],
                'cost_price' => $sku['cost_price'],
                'line_price' => $sku['line_price'],
                'price' => $sku['price'],
                'image' => $sku['image'],
                'weight' => $sku['weight'],
                'volume' => $sku['volume'],
                'goods_no' => $sku['goods_no'],
//                'spec_value_ids' =>   // 规格值集合在下面更新
            ]);
            // 创建SKU和规格的关联数据
            $specRels = $sku['specRels'];
            $specValueIds = [];
            foreach ($specRels as $rel){
                $relSpec =$afterSaveSpecs[$rel['spec_id']];
                $saveSpecValueId = $relSpec['values'][$rel['spec_value_id']]['id'];
                GoodsSkuSpecRel::create([
                    'site_id' => SiteAuthService::instance()->getSiteId(),
                    'goods_id' => $gid,
                    'sku_id' => $resSku->id,
                    'spec_id' =>$relSpec['id'],
                    'spec_value_id' => $saveSpecValueId,
                    'spec_value' => $rel['spec_value']
                ]);
                $specValueIds[] = $saveSpecValueId;
            }
            // 更新sku
            $resSku->spec_value_ids = miImplode($specValueIds);
            $resSku->save();

            // 所有规格的价格信息
            $priceArr[] = $sku['price'];
            $linePriceArr[] = $sku['line_price'];
            $costPriceArr[] = $sku['cost_price'];

            $stockTotal += $sku['stock'];

        }

        // 是否不限总库存
//        if ($stockFlag) $stockNum = -1;


        //  修改产品信息
        $goods->price = min($priceArr);
        $goods->price_max = max($priceArr);
        $goods->line_price = min($linePriceArr);
        $goods->line_price_max = max($linePriceArr);
        $goods->cost_price = min($costPriceArr);
        $goods->cost_price_max = max($costPriceArr);
        $goods->stock = $stockTotal;   // 总库存
        $goods->save();

    }

}
